//
//  OSPNNetWork.swift
//  YueChat
//
//  Created by IMac on 2024/9/21.
//

import UIKit
import Darwin


/**
 
 OSPNNetWork 功能：
 1、 tcp 链接
 2、 接收消息 并上传到OSPNNetworkService
 3、 提示链接状态
 4、 提示重连
 5、 启动和停止
 
 **/


class OspnNetWork {
    // IM 登陆主机
    var mHost: String = ""
    
    // IM 通信端口
    var mPort: in_port_t = 8100

    // Socket 文件描述符
    var mSock: Int32 = 0
    let mLock = NSLock()

    func connectToServer(hostIp:String) -> Bool {
        mSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)
        var serverAddress = sockaddr_in()
        serverAddress.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
        serverAddress.sin_family = sa_family_t(AF_INET)
        serverAddress.sin_port = CFSwapInt16(mPort)
        serverAddress.sin_addr.s_addr = inet_addr(hostIp)
        let result = withUnsafePointer(to: &serverAddress) { pointer in
            pointer.withMemoryRebound(to: sockaddr.self, capacity: 1) { reboundPointer in
                connect(mSock, UnsafePointer<sockaddr>(reboundPointer), socklen_t(MemoryLayout<sockaddr_in>.size))
            }
        }
        if result != 0 {
            close(mSock)
            mSock = 0;
            return false
        }
        return true
    }
    func disconnectToServer(){
        print("disconnectToServer")
        if mSock != 0 {
            shutdown(mSock, SHUT_RDWR)
            close(mSock)
            mSock = 0
        }
    }
    private func sendRaw(_ data:Data) -> OspnError? {
        return data.withUnsafeBytes { (pointer: UnsafeRawBufferPointer) -> OspnError? in
            guard let p = pointer.baseAddress else {return OspnError.Custom(msg: "UnsafeRawBufferPointer nil")}
            var nSend = 0
            while(nSend < pointer.count){
                let res = send(mSock, p+nSend, pointer.count-nSend, 0)
                if res <= 0 {
                    print("sendRaw \(errno)")
                    return OspnError.NetworkSend
                }
                nSend += res
            }
            return nil
        }
    }
    private func receiveRaw(length:Int) ->(Data?, OspnError?) {
        var data = Data(count: length)
        let pointer = data.withUnsafeMutableBytes { $0.baseAddress!.assumingMemoryBound(to: UInt8.self) }
        var nRead = 0
        var error:OspnError? = nil
        while(nRead < length) {
            let res = recv(mSock, pointer+nRead, Int(length-nRead), 0)
            if res <= 0 {
                print("receiveRaw \(errno)")
                error = OspnError.NetworkRecv
                break
            }
            nRead += res
        }
        if let error = error {
            return (nil, error)
        }
        return (data, nil)
    }
    func receiveFromServer() -> (Data?, OspnError?) {
        var length: Int32 = 0
        let res = withUnsafeMutableBytes(of: &length) { (pointer: UnsafeMutableRawBufferPointer) in
            recv(mSock, pointer.baseAddress, 4, 0)
        }
        if res <= 0 {
            print("\(errno)")
            return (nil, OspnError.NetworkRecv)
        }
        length = length.bigEndian
        if length > 60000 {
            print("Invalid head length: \(length)")
            return (nil, OspnError.HeadOverflow)
        }
        //print("receive length: \(length)")
        return receiveRaw(length: Int(length))
    }
    private func sendRequest(request:[String: Any]) -> OspnError?{
        guard let data = OsnUtils.toData(package: request) else {
            return OspnError.Encode
        }
        var length: Int32 = Int32(data.count).bigEndian
        let res = withUnsafeBytes(of: &length) { (pointer: UnsafeRawBufferPointer) -> Int in
            return send(mSock, pointer.baseAddress, 4, 0)
        }
        if res <= 0 {
            print("sendToServer \(errno)")
            return OspnError.NetworkSend
        }
        return sendRaw(data)
    }
    func sendToServer(request:[String: Any]) -> OspnError?{
        mLock.lock()
        let res = sendRequest(request: request)
        mLock.unlock()
        return res
    }

}

